<?php

namespace App\Services;

use App\Enum\CouponEnum;
use App\Models\OrderFlow;
use App\Models\Orders;
use App\Models\PayOrder;
use App\Models\RechargeRecord;
use App\Models\RefundOrder;
use App\Models\User;
use App\Models\UserCoupon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Overtrue\LaravelWeChat\Facade;

/**
 * 支付相关服务
 * Class PassengerPayService
 * @package App\Services
 */
class PassengerPayService extends BaseService
{


    /**
     * @param object $order 订单
     * @param string $pay_name 支付引擎 先只支持微信小程序
     * @return mixed
     */
    public function getPayData(object $order, string $pay_name = 'payWxmini')
    {

        $pay_order_info = PayOrder::query()->where('order_id', $order->id)->where('status', 0)->first(); //每条打车订单 未支付的订单同时只会存在一条

        if (!$pay_order_info)
            return $this->sendError('订单ID有误');

        if (!method_exists($this, $pay_name))
            return $this->sendError('支付驱动不存在！');

        $pay_type_arr = [
            1 => '预付款',
            2 => '订单取消责任费',
            3 => '补款',
        ];

        $order_describe = $order->distance->book_start . '-' . $order->distance->book_end . $pay_type_arr[$pay_order_info->type];

        return $this->$pay_name($pay_order_info->price, $pay_order_info->sn, $order_describe);

    }

    /**
     * 账户余额充值
     */
    public function TopUpBalance($price)
    {
        $user = Auth::user();
        $sn = uniqid('B');
        $recharge_record = new RechargeRecord();
        $recharge_record->user_id = Auth::id();
        $recharge_record->price = $price;
        $recharge_record->status = 0;
        $recharge_record->order_sn = $sn;
        $recharge_record->sn = $this->order_sn();
        $recharge_record->sn_number = 5 . date('YmdHi') . str_pad(1, 5, '0', STR_PAD_LEFT);;
        $recharge_record->note = '余额充值';
        $recharge_record->type = 0; //微信充值
        $recharge_record->after_price = bcadd($user->balance, $price, 2); //充值后金额
        $recharge_record->amount = $user->balance; //充值前金额
        $recharge_record->company_id = $user->company_id;
        if ($recharge_record->save())
            return $this->payWxmini($price, $sn, $describe = '余额充值');
    }

    /**
     * 余额支付
     */
    public function BalancePayment(int $order_id)
    {
        $orders = Orders::query()->where('id', $order_id)->where('user_id', Auth::id())->first();
        if (!$orders) return_bob('订单不存在');
        $users = User::query()->where('id', $orders->user_id)->first();
        if ($users->balance >= $orders->predict_price) {
            $this->BalanceLog($orders, $orders->predict_price); //扣款记录
            return true;
        } else {
            return_bob('余额不足');
        }
    }

    /**
     * 扣款流水
     */
    public function BalanceLog(object $orders, $total_fee)
    {
        DB::transaction(function () use ($orders, $total_fee) {
            $pay_order_info = PayOrder::query()->orderByDesc('created_at')->firstWhere('order_id', $orders->id);
            // if ($pay_order_info->status == 1) return_bob('已支付请勿重复操作');
            $pay_order_info->status = 1;
            $pay_order_info->pay_type = 2; //余额支付
            $pay_order_info->pay_sn = uniqid();
            $pay_order_info->success_time = time();
            if (!$pay_order_info->save())
                return_bob('Pay Order Error');
            switch ($pay_order_info->type) {
                case 1: ////预支付费用
                    $orders->status = '1';
                    $orders->is_pay_predict = 1;
                    $orders->real_price = $total_fee;
                    $price = $total_fee;
                    break;
                case 2: // //支付取消责任费
                    $orders->cancel_status = 0;
                    $price = 0;
                    break;
                case 3://服务结束补款
                    $orders->status = '5';
                    $orders->real_price = $orders->real_price + ($pay_order_info->price);
                    $price = $pay_order_info->price;
                    break;
            }
            if ($orders->save() === false) {
                return_bob('Pay Order Error');
            }
            $order_flow = new OrderFlow();
            $order_flow->user_id = $orders->user_id;
            $order_flow->order_id = $orders->id;
            $order_flow->order_sn = $orders->order_sn;
            $order_flow->pay_sn = $this->order_sn();
            $order_flow->type = 1; //余额支付
            $order_flow->price = $price;
            $order_flow->save();
            if ($this->logs($price, $orders->order_sn, $orders->user_id)) //记录余额支付流水
                User::query()->where('id', $orders->user_id)->update([
                    'balance' => DB::raw('balance -' . $price)
                ]);
        });
    }

    /**
     * @param $price
     * @param $order_sn
     * @param $user_id
     * 5 .  date('YmdHi') . str_pad(1, 5, '0', STR_PAD_LEFT);
     */
    public function logs($price, $order_sn, $user_id)
    {
        $user = User::query()->where('id', $user_id)->first();
        $sn = uniqid('B');
        $recharge_record = new RechargeRecord();
        $recharge_record->user_id = $user->id;
        $recharge_record->price = $price;
        $recharge_record->status = 1;
        $recharge_record->order_sn = $sn;
        $recharge_record->sn = $this->order_sn();
        $recharge_record->sn_number = $order_sn;
        $recharge_record->note = '余额支付';
        $recharge_record->type = 2; //余额支付 3 余额退款
        $recharge_record->after_price = bcsub($user->balance, $price, 2); //支付后金额
        $recharge_record->amount = $user->balance; //支付前金额
        $recharge_record->company_id = $user->company_id;
        if ($recharge_record->save()) {
            return true;
        }
        return false;
    }


    /**
     * 微信小程序支付
     * @param $price 金额
     * @param $sn 订单号
     * @param $describe 简介
     * @return array
     * @throws \App\Exceptions\BobException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    protected function payWxmini($price, $sn, $describe)
    {
        $app = Facade::payment();

        $pay_attributes = [

            'trade_type' => 'JSAPI',              // 支付方式，小程序支付使用JSAPI
            'body' => $describe,            // 订单说明
            'out_trade_no' => $sn,                  // 自定义订单号
            'total_fee' => intval(100 * $price),         // 单位：分
            'openid' => Auth::user()->open_id // 当前用户的openId

        ];

        $result = $app->order->unify($pay_attributes);

        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            $config = $app->jssdk->sdkConfig($result['prepay_id']);
            return $config;
        }

        return_bob($result['return_msg']);
    }


    /**
     * 退款
     */
    public function refund(object $order)
    {

        $refund_order_info = RefundOrder::query()->where('order_id', $order->id)->where('status', 0)->first(); //每条打车订单 待退款记录只会存在一条

        if (!$refund_order_info)
            return_bob('订单ID有误', 0, 200);

        $refund_order_info->refund_type = $refund_order_info->payOrderInfo->pay_type; // 目前仅支持原路退款

        DB::beginTransaction();
        $refund_order_info->status = 1;
        if ($refund_order_info->save() === false)
            return_bob('自动退款失败，请联系客服', 0, 200);

        if ($refund_order_info->type == 1) { //取消订单退款
            $order->cancel_status = 3;
            if ($order->save() === false) {
                DB::rollBack();
                return_bob('自动退款失败，请联系客服', 0, 200);
            }

        }

        if ($refund_order_info->type == 2) { //结束退款
            $order->status = '5';
            $order->real_price = (intval($order->real_price * 100) - intval($refund_order_info->price * 100)) / 100;
            if ($order->save() === false) {
                DB::rollBack();
                return_bob('自动退款失败，请联系客服', 0, 200);
            }

        }

        if ($refund_order_info->refund_type == 1) { //通过微信退款

            $app = Facade::payment();
            $re = $app->refund->byOutTradeNumber(
                $refund_order_info->pay_order_sn, //支付订单号
                $refund_order_info->sn, //退款号
                intval($refund_order_info->payOrderInfo->price * 100), //支付金额
                intval($refund_order_info->price * 100), //退款金额
                [
                    'notify_url' => config('wechat.notify_url.refund_notify_url'),
                ]
            );
            //todo 记录日志
            if ($re['result_code'] !== 'SUCCESS') { //申请退款失败
                DB::rollBack();
                return_bob($re['err_code_des'], 0, 200);
            }

        } elseif ($refund_order_info->refund_type == 2) { //通过余额退款
            $this->logss($refund_order_info->price, $order->order_sn, $refund_order_info->user_id, $refund_order_info->sn); //记录日志
            User::query()->where('id', $refund_order_info->user_id)
                ->update(['balance' => DB::raw('balance +' . $refund_order_info->price)]);
        } else { //暂不支持其他支付
            DB::rollBack();
            return_bob('订单异常', 0, 200);
        }

        DB::commit();
        return true;
    }

    /**
     * @param $price
     * @param $order_sn
     * @param $user_id
     * @param $sn
     */
    public function logss($price, $order_sn, $user_id, $sn)
    {
        $user = User::query()->find($user_id);
        $recharge_record = new RechargeRecord();
        $recharge_record->user_id = Auth::id();
        $recharge_record->price = $price;
        $recharge_record->status = 1;
        $recharge_record->order_sn = $sn;
        $recharge_record->sn = $this->order_sn();
        $recharge_record->sn_number = $order_sn;
        $recharge_record->note = '余额退款';
        $recharge_record->type = 3; //余额支付 3 余额退款
        $recharge_record->after_price = bcadd($user->balance, $price, 2); //退款后金额
        $recharge_record->amount = $user->balance; //退款前金额
        $recharge_record->company_id = $user->company_id;
        $recharge_record->save();
    }

    /**
     * 订单结束创建 支付/退款订单
     * @param object $order
     * @param $user_coupon_id
     * @return bool
     */
    public function createByOrderSuccess(object $order, $user_coupon_id = '')
    {

        $coupon_price = 0;
        $order_flow = OrderFlow::query()->where('order_id', $order->id)->first('type');
        DB::beginTransaction();
        if ($user_coupon_id) {
            $user_coupon_info = UserCoupon::query()->find($user_coupon_id);
            $coupon_price = $user_coupon_info->coupon->type == CouponEnum::TypeProportion ?
                $order->cost_price * (10 - $user_coupon_info->coupon->coupon_value) / 10 //折扣
                : $user_coupon_info->coupon->coupon_value; //现金

            $coupon_price = intval($coupon_price * 100) / 100;

            $user_coupon_info->use_time = time();
            $user_coupon_info->status = 2;
            $user_coupon_info->save();

        }
        $order->user_coupon_id = $user_coupon_id;
        $order->coupon_price = $coupon_price;
        $order->real_should_price = $order->should_price - $order->coupon_price;
        $order->save();
        $diff_price = $order->real_price + $order->coupon_price - $order->should_price;
        if ($diff_price > 0) { //已收款+优惠 大于 实际应收款 退款

            $pay_info_order = PayOrder::query()->where([
                'order_id' => $order->id,
                'status' => 1
            ])->first();

            $refund_order = new RefundOrder();
            $refund_order->order_id = $order->id;
            $refund_order->user_id = $order->user_id;
            $refund_order->pay_order_id = $pay_info_order->id;
            $refund_order->pay_order_sn = $pay_info_order->sn;
            $refund_order->sn = uniqid();
            $refund_order->price = $diff_price < $order->predict_price ? $diff_price : $order->predict_price;
            $refund_order->time = time();
            $refund_order->type = 2;
            $refund_order->status = 0;
            $refund_order->refund_type = $order_flow->type == 0 ? 1 : 2; //款方式 1-微信 2 余额
            $re_add_order = $refund_order->save();
        } elseif ($diff_price < 0) {//已收款+优惠 小于 实际应收款 付款

            $pay_order = new PayOrder();
            $pay_order->order_id = $order->id;
            $pay_order->user_id = $order->user_id;
            $pay_order->sn = uniqid();
            $pay_order->price = abs($diff_price);
            $pay_order->type = 3;
            $pay_order->status = 0;
            $re_add_order = $pay_order->save();

        } else { //相同
            $re_add_order = true;
        }

        DB::commit();
        return $re_add_order ? true : false;
    }

}
